<?PHP

/* Requires:
$GLOBALS['mvError']['error_log']		- PHP Error Log File
$GLOBALS['mvError']['sql_log']		- SQL Error Log File
$GLOBALS['mvError']['http_log']		- HTTP Error Log File
$GLOBALS['mvError']['user_log']		- User Error Log File
 *** Set logs to false to not log
$GLOBALS['mvError']['error_table']	- Table as defined below
$GLOBALS['mvError']['error_db'] 		- PDO link to DB
$GLOBALS['mvError']['debug']			- set to show/hide debug errors

Table Structure Example:

CREATE TABLE `error_log` (
`error_p` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`type` INT( 8 ) NOT NULL ,
`title` VARCHAR( 250 ) NOT NULL ,
`text` TEXT NULL ,
`ext` TEXT NULL ,
`when` DATETIME NOT NULL
);

mvError::userWarning('title', 'this is a sample error'); - trigger a Warning
mvError::userNotice('title', 'this is a sample error'); - trigger a Notice
mvError::userError('title', 'this is a sample error'); - trigger a Error
mvError::siteError('title', 'this is a sample error'); - trigger a Site Error
mvError::httpError('title', 'this is a sample error'); - trigger an Http Error
mvError::sqlError('title', 'this is a sample error'); - SQL Error

to set as error handler for a site:
set_error_handler(array('mvError', 'error'));

*/

define("E_SITE_ERROR", E_STRICT * 2 * 2); // doubled twice for readyness for either PHP 5.3/6 new error message
define("E_HTTP_ERROR", E_SITE_ERROR * 2);
define("E_SQL_ERROR", E_HTTP_ERROR * 2);

class mvError{

	public static function error($errno, $errstr, $errfile, $errline, $context){
		// Used for errors caught by PHP
		if($errfile == __FILE__)
			die('Error in mvError. ('.$errline.') ' . $errstr);

		$type = 'Unknown';
		switch($errno){
			case E_ERROR:			// 1 - 		Fatal Errors that will halt script execution
			case E_WARNING:			// 2 -		Non fatal Runtime Errors.
			case E_PARSE:			// 4 -		Error generated by parser.
				$type = 'System Error';
				break;
			case E_NOTICE:			// 8 -		Run-time notices
				$type = 'Code Error Notice';
				break;
			case E_CORE_ERROR:		// 16 -		Error during PHP's initial startup
			case E_CORE_WARNING:	// 32 -		Warning during PHP's initial startup
			case E_COMPILE_ERROR:	// 64 -		Error generated by zend
			case E_COMPILE_WARNING:	// 128 -	Warning generated by zend
				$type = 'Compile Error';
				break;

			// user errors should be handeled by userError
			case E_USER_ERROR:		// 256 -	Error generated by user using trigger_error() function
				mvError::userError('Error', $errstr);
				return true;
				break;
			case E_USER_WARNING:	// 512 -	Warning generated by user using trigger_error() function
				mvError::userWarning('Warning', $errstr);
				return true;
				break;
			case E_USER_NOTICE:		// 1024 -	Notice generated by user using trigger_error() function
				mvError::userNotice('Notice', $errstr);
				return true;
				break;

			case E_ALL:				// 2047 -	Defines all messages except E_STRICT
			case E_STRICT:			// 2048
				$type = 'Strict Code Notice';
				return;
				break;
		}

		$text = $type . ': (' . $errline . ')' . $errfile . ' "' . $errstr . '"';
		mvError::logError($errno, $text);

		mvError::storeError($errno, $type, $errstr, '(' . $errline . ') ' . $errfile);

		mvError::showError($errno, $type, $errstr, '(' . $errline . ') ' . $errfile);
	}

	public static function userWarning($title, $notice, $extended = null){
		mvError::logError(E_USER_WARNING, $title . ': ' . $notice);
		mvError::storeError(E_USER_WARNING, $title, $notice, $extended);
		mvError::showError(E_USER_WARNING, $title, $notice, $extended);
	}

	public static function userNotice($title, $notice, $extended = null){
		mvError::logError(E_USER_NOTICE, $title . ': ' . $notice);
		mvError::storeError(E_USER_NOTICE, $title, $notice, $extended);
		mvError::showError(E_USER_NOTICE, $title, $notice, $extended);
	}

	public static function userError($title, $error, $extended = null){
		mvError::logError(E_USER_ERROR, $title . ': ' . $error);
		mvError::storeError(E_USER_ERROR, $title, $error, $extended);
		mvError::showError(E_USER_ERROR, $title, $error, $extended);
	}

	public static function siteError($error, $extended = null){
		mvError::logError(E_SITE_ERROR, 'Site Error' . ': ' . $error);
		mvError::storeError(E_SITE_ERROR, 'Site Error', $error, $extended);
		mvError::showError(E_SITE_ERROR, 'Site Error', $error, $extended);
	}

	public static function httpError($code, $error, $extended = null){
		mvError::logError(E_HTTP_ERROR, 'HTTP Error ' . $code . ': ' . $text);
		mvError::storeError(E_HTTP_ERROR, 'HTTP Error ' . $code, $error, $extended);
		mvError::showError(E_HTTP_ERROR, 'HTTP Error ' . $code, $error, $extended);
	}

	public static function sqlError($error, $sql, $parms = array(), $extended = ''){
		$extended = "Parameters: \n" . print_r($parms, true) . "Error:\n" . $extended ;
		mvError::logError(E_SQL_ERROR, 'SQL Error ' . $sql . ': ' . $error);
		mvError::storeError(E_SQL_ERROR, 'SQL Error ' . $sql, $error, $extended);
		mvError::showError(E_SQL_ERROR, 'SQL Error ' . $sql, $error, $extended);
	}

	public static function storeError($type, $title, $text, $extended = null){
		// store error in database
		if(isset($GLOBALS['mvError']['error_db']) && $GLOBALS['mvError']['error_db']){
			try{

				$sql 	= 'INSERT INTO `'.$GLOBALS['mvError']['error_table'].'`
							(`type`, `title`, `text`, `ext`, `when`)
							VALUES (?,?,?,?, NOW())';
				$parms 	= array($type, $title, $text, $extended);
				$query 	= $GLOBALS['mvError']['error_db']->prepare_execute($sql, $parms, array(), true);

			}catch(Exception $e){
				// DB could not be contacted to enter error, try a file
				mvError::logError(E_ERROR, "DB could not be contacted to log error");
			}
		}
	}

	public static function showError($type, $title, $text, $extended = null){
		// dont show some errors except on debug
		// TODO : Set debug levels
		if(!isset($GLOBALS['mvError']['debug']) || !$GLOBALS['mvError']['debug'])
			if($type != E_SITE_ERROR && $type != E_HTTP_ERROR && $type != E_SQL_ERROR && $type != E_USER_ERROR  && $type != E_USER_WARNING  && $type != E_USER_ERROR  && $type != E_USER_NOTICE && $type != E_STRICT)
				return false;

		// store error in $_SESSION
		if(!isset($_SESSION['error_log']) || is_null($_SESSION['error_log']) )
			$_SESSION['error_log'] = array();

		$_SESSION['error_log'][] = array(
								'type'	=> $type,
								'time'	=> date('Y-m-d h:m:i'),
								'title'	=> $title,
								'text'	=> $text,
								'ext'	=> $extended
								);

	}

	public static function logError($type, $text){
		if(!isset($GLOBALS['mvError']['error_log']) || !$GLOBALS['mvError']['error_log'] )
			return false;
		$file = $GLOBALS['mvError']['error_log'];
		switch($type){
			case E_ERROR:			// 1 - 		Fatal Errors that will halt script execution
			case E_WARNING:			// 2 -		Non fatal Runtime Errors.
			case E_PARSE:			// 4 -		Error generated by parser.
			case E_NOTICE:			// 8 -		Run-time notices
			case E_CORE_ERROR:		// 16 -		Error during PHP's initial startup
			case E_CORE_WARNING:	// 32 -		Warning during PHP's initial startup
			case E_COMPILE_ERROR:	// 64 -		Error generated by zend
			case E_COMPILE_WARNING:	// 128 -	Warning generated by zend
				$file = $GLOBALS['mvError']['error_log'];
				break;

			case E_USER_ERROR:		// 256 -	Error generated by user using trigger_error() function
			case E_USER_WARNING:	// 512 -	Warning generated by user using trigger_error() function
			case E_USER_NOTICE:		// 1024 -	Notice generated by user using trigger_error() function
				$file = $GLOBALS['mvError']['user_log'];
				break;

			case E_ALL:				// 2047 -	Defines all messages except E_STRICT
			case E_STRICT:
				$file = $GLOBALS['mvError']['error_log'];
				break;
			case E_SITE_ERROR:
			case E_HTTP_ERROR:
				$file = $GLOBALS['mvError']['http_log'];
				break;
			case E_SQL_ERROR:
				$file = $GLOBALS['mvError']['sql_log'];
				break;
			default:
				$file = $GLOBALS['mvError']['error_log'];
				break;
		}

		if($file && $fp = fopen($file, 'a')){
			fwrite($fp, date('c') . ' - ' . $text . "\n");
			fclose($fp);
		}else{
			// could not open file, or file set to false...
			return false;
		}
	}

	public static function getErrors($erase = true){
		if(!isset($_SESSION['error_log']) || is_null($_SESSION['error_log']) || !$_SESSION['error_log'])
			return false;

		$log = $_SESSION['error_log'];

		$_SESSION['error_log'] = null;
		unset($_SESSION['error_log']);

		return $log;
	}
}

?>